<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="并发编程, 鸟鸟">
    <meta name="description" content="大家好，我是鸟鸟，今年20岁，喜欢打篮球，搭建的这个博客是用来记录平时的一些学习笔记和心得">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>并发编程 | 鸟鸟</title>
    <link rel="icon" type="image/png" href="/yueyueniao-gif/favicon.png">

    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/css/my.css">

    <script src="/yueyueniao-gif/libs/jquery/jquery.min.js"></script>

<meta name="generator" content="Hexo 5.0.2"><link rel="alternate" href="/yueyueniao-gif/atom.xml" title="鸟鸟" type="application/atom+xml">
<link rel="stylesheet" href="/yueyueniao-gif/css/prism-tomorrow.css" type="text/css"></head>


<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/yueyueniao-gif/" class="waves-effect waves-light">
                    
                    <img src="/yueyueniao-gif/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">鸟鸟</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/yueyueniao-gif/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/yueyueniao-gif/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/yueyueniao-gif/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/yueyueniao-gif/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/yueyueniao-gif/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/yueyueniao-gif/contact" class="waves-effect waves-light">
      
      <i class="fas fa-comments" style="zoom: 0.6;"></i>
      
      <span>留言板</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/yueyueniao-gif/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>友情链接</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/yueyueniao-gif/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">鸟鸟</div>
        <div class="logo-desc">
            
            大家好，我是鸟鸟，今年20岁，喜欢打篮球，搭建的这个博客是用来记录平时的一些学习笔记和心得
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/yueyueniao-gif/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/yueyueniao-gif/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/yueyueniao-gif/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/yueyueniao-gif/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/yueyueniao-gif/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/yueyueniao-gif/contact" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-comments"></i>
			
			留言板
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/yueyueniao-gif/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友情链接
		</a>
          
        </li>
        
        
        <li><div class="divider"></div></li>
        <li>
            <a href="https://github.com/blinkfox/hexo-theme-matery" class="waves-effect waves-light" target="_blank">
                <i class="fab fa-github-square fa-fw"></i>Fork Me
            </a>
        </li>
        
    </ul>
</div>


        </div>

        
            <style>
    .nav-transparent .github-corner {
        display: none !important;
    }

    .github-corner {
        position: absolute;
        z-index: 10;
        top: 0;
        right: 0;
        border: 0;
        transform: scale(1.1);
    }

    .github-corner svg {
        color: #0f9d58;
        fill: #fff;
        height: 64px;
        width: 64px;
    }

    .github-corner:hover .octo-arm {
        animation: a 0.56s ease-in-out;
    }

    .github-corner .octo-arm {
        animation: none;
    }

    @keyframes a {
        0%,
        to {
            transform: rotate(0);
        }
        20%,
        60% {
            transform: rotate(-25deg);
        }
        40%,
        80% {
            transform: rotate(10deg);
        }
    }
</style>

<a href="https://github.com/blinkfox/hexo-theme-matery" class="github-corner tooltipped hide-on-med-and-down" target="_blank"
   data-tooltip="Fork Me" data-position="left" data-delay="50">
    <svg viewBox="0 0 250 250" aria-hidden="true">
        <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
        <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
              fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
        <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
              fill="currentColor" class="octo-body"></path>
    </svg>
</a>
        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/yueyueniao-gif/medias/featureimages/0.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">并发编程</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/yueyueniao-gif/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        margin: 35px 0 15px 0;
        padding-left: 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        height: calc(100vh - 250px);
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    .toc-fixed .toc-link::before{
        position: fixed!important;/*当toc的位置改为fixed时，.toc-link::before也要改为fixed*/
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #toc-content .is-active-link::before {
        background-color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                          <div class="article-tag">
                            <span class="chip bg-color">无标签</span>
                          </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2020-10-19
                </div>
                

                

                
                <div class="info-break-policy">
                    <i class="far fa-file-word fa-fw"></i>文章字数:&nbsp;&nbsp;
                    7.5k
                </div>
                

                

                
            </div>
        </div>
        <hr class="clearfix">
        <div class="card-content article-card-content">
            <div id="articleContent">
                <h1 id="并发编程"><a href="#并发编程" class="headerlink" title="并发编程"></a>并发编程</h1><h2 id="进程与线程"><a href="#进程与线程" class="headerlink" title="进程与线程"></a>进程与线程</h2><h5 id="进程"><a href="#进程" class="headerlink" title="进程"></a>进程</h5><ul>
<li>程序由指令和数据组成，但这些指令要运行，数据要读些，就必须将指令加载至CPU数据加载至内存。在指令运行个过程中还需要用到磁盘，网略等设备。进程就是用来加载指令，管理内存，管理IO的</li>
<li>当一个程序被运行，从磁盘加载这个程序的代码至内存，这时就开启了一个进程。</li>
<li>进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程</li>
</ul>
<h5 id="线程"><a href="#线程" class="headerlink" title="线程"></a>线程</h5><ul>
<li>一个进程之内可以分为一到多个线程。</li>
<li>一个线程就是一个指令流，将指令流的一条指令以一定的顺序交给CPU执行。</li>
<li>java中，线程作为最小调度单位，进程作为资源分配的最少单位，在windows中进程是不活动的，只是作为线程的容器。</li>
</ul>
<h5 id="二者对比"><a href="#二者对比" class="headerlink" title="二者对比"></a>二者对比</h5><ul>
<li>进程基本上相互独立的，而线程存于进程内，是进程的一个子集。</li>
<li>进程拥有共享的资源，如内存空间等，供其内部的线程共享。</li>
<li>进程通信较为复杂<ul>
<li>同一台计算机的进程通信成为IPC</li>
<li>不同计算机之间的进程通信，需要通过网络，并遵守共同的协议，例如HTTP</li>
</ul>
</li>
<li>线程通信相对简单，因为他们共享进程内的内存，一个例子是多个线程可以访问同一个共享变量</li>
<li>线程更轻量，线程上下文切换成本一般比进程低</li>
</ul>
<h5 id="并发与并行"><a href="#并发与并行" class="headerlink" title="并发与并行"></a>并发与并行</h5><ul>
<li><p>单核cpu下，线程实际还是串行执行的，操作系统中有一个组件叫做任务调度器，将cpu时间片分给不同的线程使用，只是由于在cpu在线程间的切换时间非常快，人类感觉是同时运行的。总结一句话就是：围观串行，宏观并行。</p>
</li>
<li><p>多核cpu下，每个核都可以调度运行线程，这时候线程可以是并行的。</p>
</li>
<li><p>引用Rob Pike的一段描述：</p>
<ul>
<li>并发是同一时间应对多件事情的能力。</li>
<li>并行是同一时间动手做多件事情的能力。</li>
</ul>
</li>
</ul>
<h5 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h5><p><strong>应用制异步调用(案例一)</strong></p>
<p>从方法的调用角度来讲，如果</p>
<ul>
<li>需要等待返回结果，才能继续运行就是同步。</li>
<li>不需要等待返回结果，就能继续运行就是异步。</li>
</ul>
<p>注意：同步在多线程中还有另外一层意思，是让多个线程步调一致。</p>
<p><strong>1）设计</strong></p>
<ul>
<li>多线程可以让方法执行变为异步的（即不要巴巴干等着）比如说读取磁盘文件时，假设读取操作花费了5秒钟，如果没有线程调度机制，这5秒调用者什么都做不了，代码都得暂停….</li>
</ul>
<p><strong>2）结论</strong></p>
<ul>
<li>比如在项目中，视屏文件需要转换格式等操作比较费时，这时开一个新线程处理视屏转换，避免阻塞主线程</li>
<li>tomcat的异步servlet也是类似的目的，让用户线程处理耗时较长的操作，避免阻塞tomcat的工作线程</li>
<li>ui程序中，开县城进行其他操作，避免阻塞ui线程。</li>
</ul>
<h2 id="Java线程"><a href="#Java线程" class="headerlink" title="Java线程"></a>Java线程</h2><h4 id="创建和运行线程"><a href="#创建和运行线程" class="headerlink" title="创建和运行线程"></a>创建和运行线程</h4><p><strong>方法一，直接使用Thread</strong></p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//创建线程</span>
Thread t<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//要执行的任务</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//启动线程</span>
t<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>方法二,使用Runnable配合Thread</strong></p>
<p> 把线程和任务分开</p>
<ul>
<li>Thread代表线程</li>
<li>Runnable可运行的任务（线程要执行的代码）</li>
</ul>
<pre class=" language-java"><code class="language-java">Runnable runnable<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Runnable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//要执行的任务</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//创建线程对象(参数一是任务对象，参数二是线程名字)</span>
Thread t<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span>runnable<span class="token punctuation">,</span><span class="token string">"name"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//启动线程</span>
t<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Java 8以后可以使用lambda精简代码</p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//创建任务对象</span>
Runnable task<span class="token operator">=</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//参数1是任务对象；参数2是线程名字</span>
Thread t2<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span>task2<span class="token punctuation">,</span><span class="token string">"name"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
t2<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>方法三，FutureTask配合Thread</strong></p>
<p>FutureTask能够接收Callable类型的参数，用来处理又返回结果的情况</p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//创建任务对象</span>
Future<span class="token operator">&lt;</span>Integer<span class="token operator">></span> task3<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">FutureTask</span><span class="token operator">&lt;</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    log<span class="token punctuation">.</span><span class="token function">debig</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token number">100</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// 参数1 是任务对象；参数2是线程名字</span>
<span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span>task<span class="token punctuation">,</span><span class="token string">"name"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//主线程阻塞，同步等待task执行完毕的结果</span>
Integer result<span class="token operator">=</span>task<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"结果:&amp;#123;&amp;#125;"</span><span class="token punctuation">,</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="查看进程线程的方法"><a href="#查看进程线程的方法" class="headerlink" title="查看进程线程的方法"></a>查看进程线程的方法</h4><ul>
<li>Java<ul>
<li>jps 命令查看所有java进程</li>
<li>jstack <pid>查看某个进程的所有线程状态</pid></li>
<li>jconsole来查看某个进程中线程的运行情况</li>
</ul>
</li>
</ul>
<h4 id="常见方法"><a href="#常见方法" class="headerlink" title="常见方法"></a>常见方法</h4><table>
<thead>
<tr>
<th>方法名</th>
<th>static 功能说明</th>
<th>注意</th>
</tr>
</thead>
<tbody><tr>
<td>start()</td>
<td>启动线程，在新的线程运行run()方法中的代码</td>
<td>start()方法只是让线程就绪，里面代码并不一定立刻运行（CPU的时间片还没分给它。每个线程对象的start方法只能调用一次，如果调用多次会出现IllegalThreadStateException）</td>
</tr>
<tr>
<td>run()</td>
<td>新线程启动后会调用的方法</td>
<td>如果在构造Thread对象时传递了Runnable参数，则线程启动后会调用Runnable中的run方法，否则默认不执行任何操作。但可以创建Thread的子类对象，来覆盖默认行为。</td>
</tr>
<tr>
<td>join()</td>
<td>等待线程运行结束</td>
<td>当某个程序执行流中调用其他线程的join()方法时，调用线程将被阻塞，直到join()方法加入的join线程执行完为止</td>
</tr>
<tr>
<td>join(long n)</td>
<td>等待线程运行结束，最多等待n毫秒</td>
<td></td>
</tr>
<tr>
<td>getId()</td>
<td>获取下次讷航长整型的id 唯一id</td>
<td></td>
</tr>
<tr>
<td>getName()</td>
<td>获取线程名字</td>
<td></td>
</tr>
<tr>
<td>setName()</td>
<td>修改线程名字</td>
<td></td>
</tr>
<tr>
<td>getPriority()</td>
<td>获取线程优先级</td>
<td></td>
</tr>
<tr>
<td>getPriority(int)</td>
<td>修改线程优先级</td>
<td>java中规定线程优先级是1-10的整数，默认是5</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th>方法名</th>
<th>static 功能说明</th>
<th>明  注意</th>
</tr>
</thead>
<tbody><tr>
<td>getState()</td>
<td>获取线程状态</td>
<td>Java中线程状态使用6个enum表示，分别为：NEW,RUNNABLE,BLOCKED,WATING,TIMED_WAITING,TERMINATED</td>
</tr>
<tr>
<td>isInterrupted()</td>
<td>判断是否被打断</td>
<td>不会清除打断标记</td>
</tr>
<tr>
<td>interrupt()</td>
<td>打断线程</td>
<td>如果被打断的线程正在sleep，wait，join会导致被打断的线程抛出InterrruptedException，并且会打断清除标记；如果打断的正在运行的线程，则会设置打断标记；park的线程被打断，也会设置打断标记。</td>
</tr>
<tr>
<td>isAlive</td>
<td>线程是否存活（还没有执行完毕）</td>
<td></td>
</tr>
<tr>
<td>interrupted()</td>
<td>static                                         判断当前线程是否被打断</td>
<td>会清除打断标记</td>
</tr>
<tr>
<td>currentThread()</td>
<td>static                                              获取当前正在执行的线程</td>
<td></td>
</tr>
<tr>
<td>sleep(long n)</td>
<td>static                                      让当前执行的线程休眠n毫秒，休眠时间让出cpu的时间片给其他线程</td>
<td>时间到后重排队</td>
</tr>
<tr>
<td>yeild()</td>
<td>static                                                         提示线程调度器让出当前线程对CPU的使用</td>
<td>暂停当前正在执行的线程，把执行机会让给优先级相同或更高的线程 若队列中没有相同优先级的线程，忽略此方法</td>
</tr>
</tbody></table>
<h4 id="两阶段终止模式"><a href="#两阶段终止模式" class="headerlink" title="两阶段终止模式"></a>两阶段终止模式</h4><ul>
<li>在一个线程T1中如何”优雅“终止T2？这里【优雅】指的是给T2一个料理后事的机会。</li>
<li>错误思路：<ul>
<li>使用线程对象的stop()方法停止线程<ul>
<li>stop方法会真正杀死线程，如法国这时线程锁住了共享资源，那么当它被杀死后就再也没有机会释放锁，其他线程将永远无法获取</li>
</ul>
</li>
<li>使用System.exit(int)方法停止线程<ul>
<li>母的仅是停止一个线程，但这种做法会让整个程序都停止。</li>
</ul>
</li>
</ul>
</li>
<li><img src="https://s3.jpg.cm/2020/10/20/NlKv6.md.png" alt="NlKv6.md.png"></li>
</ul>
<h4 id="五种状态（操作系统）"><a href="#五种状态（操作系统）" class="headerlink" title="五种状态（操作系统）"></a>五种状态（操作系统）</h4><p><a target="_blank" rel="noopener" href="https://imagelol.com/image/NlhaT"><img src="https://s3.jpg.cm/2020/10/20/NlhaT.png" alt="NlhaT.png"></a></p>
<ul>
<li>【初始状态】仅是在语言层面创建了线程对象，还未与操作系统线程关联</li>
<li>【可运行状态】（就绪状态）指该线程已经被创建（与操作系统线程关联），可以由CPU调度执行</li>
<li>【运行状态】指获取了CPU时间片运行中的状态<ul>
<li>当CPU时间片用完，会从【运行状态】转换至【可运行状态】，会导致线程的上下文切换</li>
</ul>
</li>
<li>【阻塞状态】<ul>
<li>如果调用了阻塞API，如BIO读写文件，这时该线程实际不会用到CPU，会导致线程上下文切换，进入【阻塞状态】</li>
<li>等BIO操作完毕，会由操作系统唤醒阻塞的线程，转换至【可运行状态】</li>
<li>与【可运行状态】的区别是，对【阻塞状态】的线程来说只要它们一直不唤醒，调度器就一直不回考虑唤醒它们</li>
</ul>
</li>
<li>【终止状态】表示线程已经执行完毕，生命周期已经结束，不会再转换为其它状态。</li>
</ul>
<h4 id="六种状态（java）"><a href="#六种状态（java）" class="headerlink" title="六种状态（java）"></a>六种状态（java）</h4><p><strong>这是从Java API层面来描述的</strong></p>
<p><strong>根据Thread.State枚举，分为六种状态</strong></p>
<ul>
<li><p><a target="_blank" rel="noopener" href="https://imagelol.com/image/NlOGH"><img src="https://s3.jpg.cm/2020/10/20/NlOGH.png" alt="NlOGH.png"></a></p>
</li>
<li><p>NEW：初始状态，线程被构建，但是还没有调用start()方法</p>
</li>
<li><p>RUNNABLE：运行状态，Java线程将操作系统中的就绪和运行两种状态笼统地称作“运行中”</p>
</li>
<li><p>BLOCKED：阻塞状态，表示线程阻塞于锁</p>
</li>
<li><p>WAITING：等待状态，表示线程进入等待状态，进 入该状态表示当前线程需要等待其他线程做出一些特定动作（通知或中断）</p>
</li>
<li><p>TIME_WAITING：超时等待状态，该状态不同于WAITING，他是可以在指定时间自行返回</p>
</li>
<li><p>TERMIATED：终止状态，表示当前线程已经执行完毕</p>
</li>
<li><p>进入等待状态的线程需要依靠其他线程的通知才能返回到运行状态，而超时等待状态相当于在等待状态的基础上增加了超时限制，也就是超时时间到达时将会返回到运行状态。</p>
</li>
</ul>
<h2 id="共享模型之管程"><a href="#共享模型之管程" class="headerlink" title="共享模型之管程"></a>共享模型之管程</h2><h4 id="共享问题"><a href="#共享问题" class="headerlink" title="共享问题"></a>共享问题</h4><h5 id="临界区"><a href="#临界区" class="headerlink" title="临界区"></a>临界区</h5><ul>
<li><p>一个程序运行多个线程本身是没有问题的，问题出在多个线程访问<strong>共享资源</strong></p>
<ul>
<li>多个线程读<strong>共享资源</strong>其实也没有问题，在多个线程对共享资源操作时发生指令交错，就会出现问题</li>
</ul>
</li>
<li><p>一段代码如果存在对<strong>共享资源</strong>的多线程读写操作，称这段代码为<strong>临界区</strong></p>
</li>
<li><p>例如，下面代码中的临界区</p>
</li>
<li><pre class=" language-java"><code class="language-java"><span class="token keyword">static</span> <span class="token keyword">int</span> counter<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true">//临界区</span>
<span class="token punctuation">{</span>
    counter<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">idecrement</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true">//临界区</span>
<span class="token punctuation">{</span>
    counter<span class="token operator">--</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<h5 id="竞态条件"><a href="#竞态条件" class="headerlink" title="竞态条件"></a>竞态条件</h5><p>多个线程在临界区执行，由于代码的<strong>执行序列不同</strong>而导致结果无法预测，称为发生了竞态条件</p>
</li>
</ul>
<h4 id="synchronized解决方案"><a href="#synchronized解决方案" class="headerlink" title="synchronized解决方案"></a>synchronized解决方案</h4><h5 id="应用之互斥"><a href="#应用之互斥" class="headerlink" title="应用之互斥"></a>应用之互斥</h5><p>为了避免临界区的竞态条件发生，有多种手段可以达到目的。</p>
<ul>
<li>阻塞式的解决方案： synchronized,Lock</li>
<li>非阻塞式的解决方案：原子变量</li>
</ul>
<p><strong>注意</strong></p>
<p>虽然java中互斥和同步都可以采用synchronized关键字来完成，但它们还是有区别的：</p>
<ul>
<li>互斥是保证临界区的竞态条件发生，同一时刻只能有一个线程执行临界区代码。</li>
<li>同步是由于线程执行的先后顺序不同个，需要一个线程等待其他线程运行到某个点。</li>
</ul>
<h5 id="synchronized"><a href="#synchronized" class="headerlink" title="synchronized"></a>synchronized</h5><p><strong>synchronized，即俗称【对象锁】</strong>：它采用互斥的方式让同一时刻之多只有一个线程能持有【对象锁】，其他线程在想获取这个【对象锁】时就会阻塞住。这样就鞥保证拥有锁的线程可以安全的执行临界区的代码，不用担心上下文切换。</p>
<p><strong>语法</strong></p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">synchronized</span><span class="token punctuation">(</span>对象<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    临界区
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<p><strong>方法上的synchronized</strong></p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">class</span> <span class="token class-name">Test</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">synchronized</span> <span class="token keyword">void</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>

    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
等价于
<span class="token keyword">class</span> <span class="token class-name">Test</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">synchronized</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>

        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<pre class=" language-java"><code class="language-java"><span class="token keyword">class</span> <span class="token class-name">Test</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">synchronized</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>

    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
等价于
<span class="token keyword">class</span> <span class="token class-name">Test</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">synchronized</span><span class="token punctuation">(</span>Test<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h4 id="Monitor"><a href="#Monitor" class="headerlink" title="Monitor"></a>Monitor</h4><h5 id="java对象头"><a href="#java对象头" class="headerlink" title="java对象头"></a>java对象头</h5><p>synchronized用的锁是存在Java对象头里面的。</p>
<p>​       如果对象时数组类型，则虚拟机用3个字宽（Word）存储对象头。</p>
<p>​       如果对象是非数组类型，则虚拟机用2个字宽（Word）存储对象头。</p>
<p>​       在32位虚拟机中，1字宽等与4字节，即32bit。</p>
<p>java的对象头由以下三部分组成：</p>
<pre><code>1，Mark Word                             （32/64bit）                    存储对象的hashCode或锁信息

2，指向类的指针（Class Metadata A）         （32/64bit）                    存储到对象类型数据的指针

3，数组长度（Array length    ）             （32/32bit）                   数组的长度（如果当前对象是数组）</code></pre>
<p>java对象头里的Mrak Word里默认存储对象 的HashCode、分代年龄和锁标记位。32位JVM的Mark Word的默认存储结构如下所示：</p>
<pre><code>锁状态           25bit                4bit             1bit是否偏向锁               2bit所标志位
无锁状态        对象的hashCode       对象分代年龄               0                          01</code></pre>
<p>在运行期间，Mark Word里存储的数据会随着所标志位的变化而变化。Mark Word可能变化为存储以下4中数据，如下所示：</p>
<p><img src="https://n1.i5h5.com/2020/10/12/tF7lw.png"></p>
<h5 id="Monitor（锁）"><a href="#Monitor（锁）" class="headerlink" title="Monitor（锁）"></a>Monitor（锁）</h5><ul>
<li><p>Monitor被翻译为<strong>监听器</strong>或<strong>管程</strong></p>
</li>
<li><p>每个java对象都可以关联一个Monitor对象，如果使用synchronized给对象上锁（重量级）之后，该对象头的Mark Word中就被设置指向Monitor对象的指针</p>
</li>
<li><p>Monitor结构如下：</p>
<ul>
<li><a target="_blank" rel="noopener" href="https://imagelol.com/image/NA5Jh"><img src="https://s3.jpg.cm/2020/10/21/NA5Jh.png" alt="NA5Jh.png"></a></li>
<li>刚开始Monitor中Owner为null</li>
<li>当Thread2执行synchronized(obj)就会将Monitor的所有者Owner置为Thread2，Monitor中只能有一个Owner</li>
<li>在Thread2上锁的过程中，如果Thread3，Thread4，THread5也来执行synchronized(obj)，就会进入EntryList BLOCKED</li>
<li>Thread2执行完同步代码的内容，然后唤醒EntryList中等待的线程来竞争锁，竞争的时候是非公平的</li>
<li>途中WaitSet中的Thread0，Threa是之前获得过锁，但条件不满足进入WAITING状态的线程，后面将wait-notify时会分析。</li>
<li><strong>注意</strong><ul>
<li>synchronized必须是进入同一个对象的monitor才有上述的效果。</li>
<li>不加synchronized的对象不会关联监视器，不遵从以上规则。</li>
</ul>
</li>
</ul>
</li>
</ul>
<h5 id="轻量级锁"><a href="#轻量级锁" class="headerlink" title="轻量级锁"></a>轻量级锁</h5><p>使用场景：如果一个对象虽然有多线程访问，但多线程访问的时间是错开的（也就是没有竞争），那么可以使用轻量级锁来优化。</p>
<p>轻量级锁对使用者是透明的，即语法仍然是synchronized</p>
<p>假设有两个同步方法块，利用同一个对象加锁</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">static</span> <span class="token keyword">final</span> Object obj<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">method1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">synchronized</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//同步块A</span>
        <span class="token function">method2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">method2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">synchronized</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//同步块B</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<ul>
<li><p>创建锁记录（LockRecord）对象，每个线程的栈帧都会包含一个锁记录的结构，内部可以存储锁定对象的Mark Word</p>
<p><a target="_blank" rel="noopener" href="https://imagelol.com/image/NAUnw"><img src="https://s3.jpg.cm/2020/10/21/NAUnw.md.png" alt="NAUnw.md.png"></a></p>
</li>
</ul>
<ul>
<li><p>让锁记录的Object reference指向锁对象，并尝试用cas替换Object的Mark Word，将Mark Word的值存入锁记录</p>
<p><a target="_blank" rel="noopener" href="https://imagelol.com/image/NAbt8"><img src="https://s3.jpg.cm/2020/10/21/NAbt8.md.png" alt="NAbt8.md.png"></a></p>
</li>
<li><p>如果cas替换成功，对象头中存储量锁记录地址和状态00，表示由该线程给对象加锁，这时图示如下</p>
<p><a target="_blank" rel="noopener" href="https://imagelol.com/image/NAuzi"><img src="https://s3.jpg.cm/2020/10/21/NAuzi.md.png" alt="NAuzi.md.png"></a></p>
</li>
<li><p>如果cas失败，有两种情况</p>
<ul>
<li>如果是其他线程已经持有了该Object的轻量级锁，这时表明有竞争，进入锁膨胀过程</li>
<li>如果使自己执行了synchronized锁重入，那么再添加一套Lock Record作为重入的计数</li>
<li><img src="https://s3.jpg.cm/2020/11/11/SxOpH.png" alt="SxOpH.png"></li>
</ul>
</li>
<li><p>当退出synchronized代码块（解锁时）如果有取值为null的锁记录，表示由重入，这时重置锁记录，表示重入计数减一</p>
<p>-<a target="_blank" rel="noopener" href="https://imagelol.com/image/NAktz"><img src="https://s3.jpg.cm/2020/10/21/NAktz.md.png" alt="NAktz.md.png"></a></p>
</li>
<li><p>党退出synchroinzed代码块（解锁时）锁记录的值不为null，这时使用cas将Mark Work的值恢复给对象头</p>
<ul>
<li>成功，则解锁成功。</li>
<li>失败，说明轻量级锁进行了锁膨胀或者已经升级为重量级锁，进入重量级锁解锁流程。</li>
</ul>
</li>
</ul>
<h5 id="锁膨胀"><a href="#锁膨胀" class="headerlink" title="锁膨胀"></a>锁膨胀</h5><p>如果在尝试加轻量级锁的过程中。CAS操作无法成功，这时一种情况就是有其它线程为此对象加上了轻量级锁（有竞争），这时需要进行锁膨胀，将轻量级锁变为重量级锁。</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">static</span> Object obj<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">methods</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">synchronized</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//同步块</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<ul>
<li><p>当Thread1进行轻量级加锁时，Thread0已经对该对象加了轻量级锁</p>
<p><a target="_blank" rel="noopener" href="https://imagelol.com/image/NXLbk"><img src="https://s3.jpg.cm/2020/10/21/NXLbk.png" alt="NXLbk.png"></a></p>
</li>
<li><p>这时Thread1加轻量级锁失败，进入锁膨胀</p>
<ul>
<li>即为Object对象申请Monitor锁，让Object指向重量级锁地址。</li>
<li>然后自己进入Monitor的EntryList BLOCKED</li>
<li><a target="_blank" rel="noopener" href="https://imagelol.com/image/NX5yC"><img src="https://s3.jpg.cm/2020/10/21/NX5yC.png" alt="NX5yC.png"></a></li>
</ul>
</li>
<li><p>当Thread0退出同步块解锁时，使用cas将Mark Word的值恢复给对象头，失败。这时会进入重量级解锁流程，即按照Monitor地址找到Monitor对象，设置Owner为null，唤醒EntryList中BLOCKED线程</p>
</li>
</ul>
<h5 id="自旋优化"><a href="#自旋优化" class="headerlink" title="自旋优化"></a>自旋优化</h5><p>重量级锁竞争的时候，还可以使用自旋来进行优化，若果当前线程自旋成功（即这时候持锁想爱你成已经退出了同步块，释放了锁），这时当前线程就可以避免阻塞。</p>
<p> <a target="_blank" rel="noopener" href="https://imagelol.com/image/NXe2z"><img src="https://s3.jpg.cm/2020/10/21/NXe2z.png" alt="NXe2z.png"></a></p>
<p><a target="_blank" rel="noopener" href="https://imagelol.com/image/NX6Pu"><img src="https://s3.jpg.cm/2020/10/21/NX6Pu.png" alt="NX6Pu.png"></a></p>
<ul>
<li>在java 6之后自旋锁是自适应的，比如对象刚刚的一次自旋操作成功过，那么认为这次自旋成功可能性会高，就多自旋几次；反之；就少自旋甚至不自旋，总之，比较智能。</li>
<li>自旋会占用CPU时间，单核CPU自旋就是浪费，多核CPU自旋才能发挥优势。</li>
<li>java 7之后不能控制是否开启自旋功能。</li>
</ul>
<h4 id="wait-notify"><a href="#wait-notify" class="headerlink" title="wait/notify"></a>wait/notify</h4><p><img src="https://s3.jpg.cm/2020/11/11/SxZaL.png" alt="SxZaL.png"></p>
<ul>
<li>Owner线程发现条件不满足，调用wait方法，即可进入WaitSet变为WAITING状态</li>
<li>BLOCKED和WAITING的线程都处于阻塞状态，不占用CPU时间片</li>
<li>BLOCKED线程会在Owner线程释放锁时唤醒</li>
<li>WAITING线程会在Owner线程调用notify或notifyAll时唤醒，但唤醒后并不意味着立刻获得锁，仍需进入EntryList重新竞争</li>
</ul>
<p><strong>sleep（long  n）和wait（long n）的区别</strong></p>
<ol>
<li>sleep是Thread的静态方法，而wait是Object的方法。</li>
<li>sleep不需要强制和synchronized配合使用，单wait需要和synchronized一起用。</li>
<li>sleep在睡眠的同时，不会释放对象锁的，但wait在等待的时候会释放对象锁。</li>
</ol>
<h4 id="Park-Unpark"><a href="#Park-Unpark" class="headerlink" title="Park/Unpark"></a>Park/Unpark</h4><p>它们是LockSupport类中的方法</p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//暂停当前线程</span>
LockSupport<span class="token punctuation">.</span><span class="token function">park</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//恢复某个线程的运行</span>
LockSupport<span class="token punctuation">.</span><span class="token function">unpark</span><span class="token punctuation">(</span>暂停线程对象<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>特点：</strong></p>
<p>与Object的wait和notify相比</p>
<ul>
<li>wait，notify和notifyAll必须配合Object Monitor一起使用，而unpark不必</li>
<li>park和unpark是以线程为单位来【阻塞】和【唤醒】线程，而notify只能随机唤醒一个等待线程，notifyAll是唤醒所有等待线程，就不那么【精确】。</li>
<li>park和unpark可以先unpark，而waii和notify不能先notify</li>
</ul>
<h4 id="活跃性"><a href="#活跃性" class="headerlink" title="活跃性"></a>活跃性</h4><p><strong>死锁</strong></p>
<ul>
<li>定位死锁<ul>
<li>检测死锁可以使用jconsole工具，或者使用jps定位进程id，再用jstack定位死锁：</li>
</ul>
</li>
</ul>
<p><strong>活锁</strong></p>
<p>活锁出现在两个线程互相改变对方的结束条件，最后谁也无法结束</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">static</span> <span class="token keyword">volatile</span> <span class="token keyword">int</span> count<span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">;</span>
<span class="token keyword">static</span> <span class="token keyword">final</span> Object lock<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> voi <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//期望减到0退出循环</span>
        <span class="token keyword">while</span><span class="token punctuation">(</span>count<span class="token operator">></span><span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
          <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            count<span class="token operator">--</span><span class="token punctuation">;</span>
            log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"count:&amp;#123;&amp;#125;"</span><span class="token punctuation">,</span>count<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span><span class="token string">"t1"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

      <span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//期望加到20退出循环</span>
        <span class="token keyword">while</span><span class="token punctuation">(</span>count<span class="token operator">></span><span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
          <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            count<span class="token operator">++</span><span class="token punctuation">;</span>
            log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"count:&amp;#123;&amp;#125;"</span><span class="token punctuation">,</span>count<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span><span class="token string">"t2"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<p><strong>饥饿</strong></p>
<p>很多教程把饥饿定义为，一个线程由于优先级太低，始终得不到CPU调度执行，也不能够结束，饥饿的情况不易演示，讲读写锁的时候回涉及到饥的问题。</p>
<h4 id="ReenreantLock"><a href="#ReenreantLock" class="headerlink" title="ReenreantLock"></a>ReenreantLock</h4><p>相对于synchronized它具备如下特点</p>
<ul>
<li><p>可中断</p>
</li>
<li><p>课设置超时时间</p>
</li>
<li><p>可设置为公平锁</p>
</li>
<li><p>支持多个条件变量</p>
</li>
<li><p>与synchronized一样，都支持可重入</p>
</li>
<li><p>基本语法</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">private</span> <span class="token keyword">static</span> RenntrantLock lock<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">RenntrantLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//获取锁</span>
lock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
reentrantLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//临界区</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token keyword">finally</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//释放锁</span>
    lock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
</ul>
<h2 id="AQS源码分析"><a href="#AQS源码分析" class="headerlink" title="AQS源码分析"></a>AQS源码分析</h2><h3 id="自己实现一把锁"><a href="#自己实现一把锁" class="headerlink" title="自己实现一把锁"></a>自己实现一把锁</h3><h4 id="自旋"><a href="#自旋" class="headerlink" title="自旋"></a>自旋</h4><p>缺点：</p>
<ul>
<li>耗费cpu资源。没有竞争到锁的线程会一直占用cpu资源进行cas操作。</li>
</ul>
<p>思路：</p>
<ul>
<li>让得不到锁线程让出CPU</li>
</ul>
<pre class=" language-java"><code class="language-java"><span class="token keyword">volatile</span> <span class="token keyword">int</span> status <span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//标识----是否有线程在同步块------是否有线程上锁成功</span>
voidlock（）<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token function">whiel</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">comparaAndSet</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//如果修改status为1，表明有线程在同步块，修改不成功返回false，一直死循环，直到修改成功</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>

<span class="token keyword">void</span> <span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>

<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>

<span class="token keyword">boolean</span> <span class="token function">compareAndSet</span><span class="token punctuation">(</span><span class="token keyword">int</span> except<span class="token punctuation">,</span><span class="token keyword">int</span> newValue<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//cas操作，修改status成功则返回true</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h4 id="yield-自旋"><a href="#yield-自旋" class="headerlink" title="yield+自旋"></a>yield+自旋</h4><ul>
<li>要解决自旋锁的心梗问题必须让竞争锁失败的线程不空转，而是在获取不到锁的时候让出cpu资源。</li>
<li>yeild()方法就能让出cpu资源，当线程竞争锁失败时，会调用yield方法让出cpu。</li>
<li>但是并没有完全解决问题，yield方法只是让出当前cpu，有可能操作系统下次还是选择该线程。</li>
</ul>
<pre class=" language-java"><code class="language-java"><span class="token keyword">volatile</span> <span class="token keyword">int</span> status<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">comparaAndSet</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token function">yield</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//自己实现</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    status<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h4 id="sleep-自旋"><a href="#sleep-自旋" class="headerlink" title="sleep+自旋"></a>sleep+自旋</h4><p>缺点：</p>
<ul>
<li>睡眠多久不确定</li>
</ul>
<pre class=" language-java"><code class="language-java"><span class="token keyword">volatile</span> <span class="token keyword">int</span> status<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">comparaAndSet</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//自己实现</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    status<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h4 id="park-自旋"><a href="#park-自旋" class="headerlink" title="park+自旋"></a>park+自旋</h4><pre class=" language-java"><code class="language-java"><span class="token keyword">volatile</span> <span class="token keyword">int</span> status<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>
Queue parkQueue<span class="token punctuation">;</span><span class="token comment" spellcheck="true">//集合  数组  list</span>
<span class="token keyword">void</span> <span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">comparaAndSet</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token function">park</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//lock 20</span>
    。。。。。。
    <span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
     status<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>
   <span class="token function">lock_notigy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">park</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//将当期线程加入到等待队列</span>
    parkQueue<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>currentThread<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//将当期线程释放cpu  阻塞</span>
    <span class="token function">repleasaCpu</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">lock_notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//得到要唤醒的线程头部线程</span>
    Thread t<span class="token operator">=</span>parkQueue<span class="token punctuation">.</span><span class="token function">header</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//唤醒等待线程</span>
    <span class="token function">unpark</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h3 id="公平锁"><a href="#公平锁" class="headerlink" title="公平锁"></a>公平锁</h3><ul>
<li><p>首先点开Reentranrt源码看到如下,在new ReentrantLock()的时候，默认传参为false也，就是默认使用非公平锁，如果想使用公平锁，new ReentrantLock()的时候传参true。</p>
</li>
<li><pre class=" language-java"><code class="language-java"> <span class="token keyword">public</span> <span class="token function">ReentrantLock</span><span class="token punctuation">(</span><span class="token keyword">boolean</span> fair<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        sync <span class="token operator">=</span> fair <span class="token operator">?</span> <span class="token keyword">new</span> <span class="token class-name">FairSync</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">NonfairSync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span></code></pre>
</li>
<li><p>然后先看公平锁，点进FairSync这个类，发现他是和非公平锁NonfairSync一样都继承了Sync。</p>
</li>
<li><p>在这个FairSync类中找到lock的加锁方法</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token function">acquire</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>发现它调用了一个acquire(1)方法，点进去瞅瞅。</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">acquire</span><span class="token punctuation">(</span><span class="token keyword">int</span> arg<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">tryAcquire</span><span class="token punctuation">(</span>arg<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
            <span class="token function">acquireQueued</span><span class="token punctuation">(</span><span class="token function">addWaiter</span><span class="token punctuation">(</span>Node<span class="token punctuation">.</span>EXCLUSIVE<span class="token punctuation">)</span><span class="token punctuation">,</span> arg<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token function">selfInterrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>点进去就到了最精髓的地方了</p>
<pre class=" language-java"><code class="language-java"> <span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">acquire</span><span class="token punctuation">(</span><span class="token keyword">int</span> arg<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">tryAcquire</span><span class="token punctuation">(</span>arg<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
            <span class="token function">acquireQueued</span><span class="token punctuation">(</span><span class="token function">addWaiter</span><span class="token punctuation">(</span>Node<span class="token punctuation">.</span>EXCLUSIVE<span class="token punctuation">)</span><span class="token punctuation">,</span> arg<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token function">selfInterrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>可以看到if里面有三个方法tryAcquire()、addWaiter()、acquireQueued()，我们一一来看</p>
</li>
<li><p>先看第一个tryAcquire(),点进去瞅瞅</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token keyword">boolean</span> <span class="token function">tryAcquire</span><span class="token punctuation">(</span><span class="token keyword">int</span> acquires<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token keyword">final</span> Thread current <span class="token operator">=</span> Thread<span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">int</span> c <span class="token operator">=</span> <span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">hasQueuedPredecessors</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
                    <span class="token function">compareAndSetState</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> acquires<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                    <span class="token function">setExclusiveOwnerThread</span><span class="token punctuation">(</span>current<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
                <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
            <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
            <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>current <span class="token operator">==</span> <span class="token function">getExclusiveOwnerThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                <span class="token keyword">int</span> nextc <span class="token operator">=</span> c <span class="token operator">+</span> acquires<span class="token punctuation">;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>nextc <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
                    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">"Maximum lock count exceeded"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token function">setState</span><span class="token punctuation">(</span>nextc<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>首先这段代码 int c=getState()，判断是否这把锁已经拥有线程了，如果没有，也就是c==0，再次判断队列是否为空，如果为空，就使用cas给线程加锁，然后返回true。</p>
</li>
<li><p>如果c !=0，则判断是否为重入锁，如果为重入锁，返回true。</p>
</li>
<li><p>如果上述两种情况都不满足，直接返回false。</p>
</li>
<li><p>因为tryAcquire()方法返回false，则!tryAcquire()为true，说明线程加锁失败，需要入队列阻塞等待</p>
</li>
<li><p>然后看addWaiter()方法,点进去瞅瞅</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">private</span> Node <span class="token function">addWaiter</span><span class="token punctuation">(</span>Node mode<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        Node node <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Node</span><span class="token punctuation">(</span>Thread<span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> mode<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">// Try the fast path of enq; backup to full enq on failure</span>
        Node pred <span class="token operator">=</span> tail<span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>pred <span class="token operator">!=</span> null<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            node<span class="token punctuation">.</span>prev <span class="token operator">=</span> pred<span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">compareAndSetTail</span><span class="token punctuation">(</span>pred<span class="token punctuation">,</span> node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                pred<span class="token punctuation">.</span>next <span class="token operator">=</span> node<span class="token punctuation">;</span>
                <span class="token keyword">return</span> node<span class="token punctuation">;</span>
            <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
        <span class="token function">enq</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> node<span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>一开始如果队列不为空，进行入队列操作，如果队列为空，则pred==tail==null,所以执行enq(node)方法，初始化队列，然后将节点入队列，点击去enq(node)瞅瞅</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">private</span> Node <span class="token function">enq</span><span class="token punctuation">(</span><span class="token keyword">final</span> Node node<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            Node t <span class="token operator">=</span> tail<span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>t <span class="token operator">==</span> null<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// Must initialize</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">compareAndSetHead</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Node</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                    tail <span class="token operator">=</span> head<span class="token punctuation">;</span>
            <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">else</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                node<span class="token punctuation">.</span>prev <span class="token operator">=</span> t<span class="token punctuation">;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">compareAndSetTail</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                    t<span class="token punctuation">.</span>next <span class="token operator">=</span> node<span class="token punctuation">;</span>
                    <span class="token keyword">return</span> t<span class="token punctuation">;</span>
                <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
            <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>这段代码很精髓了，一个死循环，执行两次，第一次刚进来，节点为空t==null，初始化队列。new了一个节点做第一个，这个节点没有所属队列。</p>
</li>
<li><p>然后执行第二次循环，返现t!==null了，然后将传入的节点入队，完成入队列操作</p>
</li>
<li><p>入队列成功后执行第三个方法acquireQueued(),点进去瞅瞅</p>
<pre class=" language-java"><code class="language-java"> <span class="token keyword">final</span> <span class="token keyword">boolean</span> <span class="token function">acquireQueued</span><span class="token punctuation">(</span><span class="token keyword">final</span> Node node<span class="token punctuation">,</span> <span class="token keyword">int</span> arg<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">boolean</span> failed <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token keyword">boolean</span> interrupted <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
            <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                <span class="token keyword">final</span> Node p <span class="token operator">=</span> node<span class="token punctuation">.</span><span class="token function">predecessor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>p <span class="token operator">==</span> head <span class="token operator">&amp;&amp;</span> <span class="token function">tryAcquire</span><span class="token punctuation">(</span>arg<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                    <span class="token function">setHead</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    p<span class="token punctuation">.</span>next <span class="token operator">=</span> null<span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// help GC</span>
                    failed <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
                    <span class="token keyword">return</span> interrupted<span class="token punctuation">;</span>
                <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">shouldParkAfterFailedAcquire</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span> node<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span>
                    <span class="token function">parkAndCheckInterrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                    interrupted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
            <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">finally</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>failed<span class="token punctuation">)</span>
                <span class="token function">cancelAcquire</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>可能正在执行入队列操作的时候，占有锁的线程unpark()释放锁了</p>
</li>
<li><p>final Node p = node.predecessor(); 判断上一个节点是否为头部节点，如果是头部 if (p == head &amp;&amp; tryAcquire(arg)){}可以看到又调用了tryAcquire()方法，自旋了一次。如果自旋失败，返回false，则执行if(shouldParkAfterFailedAcquire(p, node) &amp;&amp;</p>
<pre><code>                parkAndCheckInterrupt())里面的第一个方法shouldParkAfterFailedAcquire()，点进去瞅瞅</code></pre>
<pre class=" language-java"><code class="language-java"><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">boolean</span> <span class="token function">shouldParkAfterFailedAcquire</span><span class="token punctuation">(</span>Node pred<span class="token punctuation">,</span> Node node<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">int</span> ws <span class="token operator">=</span> pred<span class="token punctuation">.</span>waitStatus<span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>ws <span class="token operator">==</span> Node<span class="token punctuation">.</span>SIGNAL<span class="token punctuation">)</span>
            <span class="token comment" spellcheck="true">/*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */</span>
            <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>ws <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token comment" spellcheck="true">/*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             */</span>
            <span class="token keyword">do</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
                node<span class="token punctuation">.</span>prev <span class="token operator">=</span> pred <span class="token operator">=</span> pred<span class="token punctuation">.</span>prev<span class="token punctuation">;</span>
            <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>pred<span class="token punctuation">.</span>waitStatus <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            pred<span class="token punctuation">.</span>next <span class="token operator">=</span> node<span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">else</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token comment" spellcheck="true">/*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */</span>
            <span class="token function">compareAndSetWaitStatus</span><span class="token punctuation">(</span>pred<span class="token punctuation">,</span> ws<span class="token punctuation">,</span> Node<span class="token punctuation">.</span>SIGNAL<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>上一个节点的ws默认为0，所以走到最后一个else，执行compareAndSetWaitStatus(pred, ws, Node.SIGNAL);让上一个节点的ws=-1,然后返回false，当返回false时，又会自旋一次，然后再次执行shouldParkAfterFailedAcquire()方法,这时ws=-1，直接返回true</p>
</li>
<li><p>当返回为true时，执行parkAndCheckInterrupt()方法，点进去瞅瞅</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">boolean</span> <span class="token function">parkAndCheckInterrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        LockSupport<span class="token punctuation">.</span><span class="token function">park</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> Thread<span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
</li>
<li><p>阻塞当前线程。</p>
<h2 id="线程池"><a href="#线程池" class="headerlink" title="线程池"></a>线程池</h2></li>
</ul>
<p><img src="https://s3.jpg.cm/2020/11/11/SxxZW.png" alt="SxxZW.png"></p>
<h4 id="线程池状态"><a href="#线程池状态" class="headerlink" title="线程池状态"></a>线程池状态</h4><p><img src="https://s3.jpg.cm/2020/11/11/SxMA2.png" alt="SxMA2.png"></p>
<h4 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h4><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token function">ThreadPollExecutor</span><span class="token punctuation">(</span><span class="token keyword">int</span> corePoolSize<span class="token punctuation">,</span>
                          <span class="token keyword">int</span> maximumPoolSize<span class="token punctuation">,</span>
                          <span class="token keyword">long</span> keepAliveTime<span class="token punctuation">,</span>
                          TimeUnit unit<span class="token punctuation">,</span>
                          BlockingQueue<span class="token operator">&lt;</span>Runnable<span class="token operator">></span> workQueue<span class="token punctuation">,</span>
                          ThreadFactory threadFactoty<span class="token punctuation">,</span>
                          RejectedExecutionHandler handler
<span class="token punctuation">)</span></code></pre>
<ul>
<li>corePoolSize              核心线程数目（最多保留线程数）</li>
<li>maximumPoolSize   最大线程 数目</li>
<li>keepAliveTime          生存时间-针对救急线程</li>
<li>unit                             时间单位-针对救急线程</li>
<li>threadFactoty           线程工厂-可以为线程创建时起个好名字</li>
<li>handler                         拒绝策略</li>
</ul>
<h4 id="newFixedThreadPool（固定大小线程池）"><a href="#newFixedThreadPool（固定大小线程池）" class="headerlink" title="newFixedThreadPool（固定大小线程池）"></a>newFixedThreadPool（固定大小线程池）</h4><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">static</span> ExecutorService <span class="token function">newFixedThreadPool</span><span class="token punctuation">(</span><span class="token keyword">int</span> nThreads<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span>nThreads<span class="token punctuation">,</span>nThreads<span class="token punctuation">,</span>
                                  0L<span class="token punctuation">,</span>TimeUnti<span class="token punctuation">.</span>MILLISECONDS<span class="token punctuation">,</span>
                                  <span class="token keyword">new</span> <span class="token class-name">LinkedBlockingQueue</span><span class="token operator">&lt;</span>Runnable<span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<ul>
<li>特点<ul>
<li>核心线程数==最大线程数（没有救急线程被创建），因此也无需要超时时间</li>
<li>阻塞队列是无界的，可以放任意数量的任务。</li>
<li>适用于任务量已知，相对耗时的任务</li>
</ul>
</li>
</ul>
<h4 id="newCachedThreadPool（带缓冲线程池）"><a href="#newCachedThreadPool（带缓冲线程池）" class="headerlink" title="newCachedThreadPool（带缓冲线程池）"></a>newCachedThreadPool（带缓冲线程池）</h4><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">static</span> ExecutorService <span class="token function">newCachedThreadPool</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span>Integer<span class="token punctuation">.</span>MAX_VALUE<span class="token punctuation">,</span>
                                  60L<span class="token punctuation">,</span>TimeUnit<span class="token punctuation">.</span>SECONDS<span class="token punctuation">,</span>
                                  <span class="token keyword">new</span> <span class="token class-name">SynchronousQueue</span><span class="token operator">&lt;</span>Runnable<span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<ul>
<li>核心线程数是0，最大线程数是Integer.MAX_VALUE，救急线程是空闲生存时间是60s，意味着<ul>
<li>全部都是救急线程（60s后可以回收）</li>
<li>就及线程可以无限创建</li>
</ul>
</li>
<li>队列采用了SynchronousQueue实现特点是，他没有容量，没有线程来取是放不进去的（一手交钱，一手交货）</li>
<li>整个线程池表现为线程数会根据任务量不断增长，没有上线，当任务执行完毕，空闲一分钟后释放线程。适合任务数比较秘籍，但每个任务执行时间较短的情况。</li>
</ul>
<h4 id="newSingleThreadExecutor（单线程线程池）"><a href="#newSingleThreadExecutor（单线程线程池）" class="headerlink" title="newSingleThreadExecutor（单线程线程池）"></a>newSingleThreadExecutor（单线程线程池）</h4><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">static</span> ExecutorService <span class="token function">newSingleThreadExecutor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">FinalizableDelegatedExecutorService</span>
            <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span>
                                    0L<span class="token punctuation">,</span> TimeUnit<span class="token punctuation">.</span>MILLISECONDS<span class="token punctuation">,</span>
                                    <span class="token keyword">new</span> <span class="token class-name">LinkedBlockingQueue</span><span class="token operator">&lt;</span>Runnable<span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<ul>
<li><p>使用场景：</p>
<p>希望多个任务排队执行。线程固定为1，任务数多于1时，会放入无界队列排队。任务执行完毕，这唯一的线程也不会被释放。</p>
</li>
<li><p>区别：</p>
<ul>
<li>自己创建一个单线程串行执行任务，如果任务执行失败而终止那么没有任何补救措施，而线程池还会新建一个线程保证池的正常工作。 </li>
</ul>
</li>
</ul>
<h4 id="提交任务"><a href="#提交任务" class="headerlink" title="提交任务"></a>提交任务</h4><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//执行任务</span>
<span class="token keyword">void</span> <span class="token function">execute</span><span class="token punctuation">(</span>Runnable command<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//提交任务task，用返回值Future获得任务执行结果</span>
<span class="token operator">&lt;</span>T<span class="token operator">></span> Future<span class="token operator">&lt;</span>T<span class="token operator">></span> <span class="token function">submit</span><span class="token punctuation">(</span>Callable<span class="token operator">&lt;</span>T<span class="token operator">></span> task<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//提交tasks中所有任务</span>
<span class="token operator">&lt;</span>T<span class="token operator">></span> List<span class="token operator">&lt;</span>Future<span class="token operator">&lt;</span>T<span class="token operator">>></span> <span class="token function">incokeAll</span><span class="token punctuation">(</span>Collection<span class="token operator">&lt;</span><span class="token operator">?</span> extend Callable<span class="token operator">&lt;</span><span class="token operator">></span>T<span class="token operator">></span> tasks<span class="token punctuation">)</span>
    <span class="token keyword">throws</span> InterruptedException<span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//提交tasks中所有任务，带超时时间</span>
<span class="token operator">&lt;</span>T<span class="token operator">></span> List<span class="token operator">&lt;</span>Future<span class="token operator">&lt;</span>T<span class="token operator">>></span> <span class="token function">invokeAll</span><span class="token punctuation">(</span>Collection<span class="token operator">&lt;</span><span class="token operator">?</span> <span class="token keyword">extends</span> <span class="token class-name">Callable</span><span class="token operator">&lt;</span>T<span class="token operator">>></span> tasks<span class="token punctuation">,</span><span class="token keyword">long</span> timeout<span class="token punctuation">,</span>TimeUnit unit<span class="token punctuation">)</span>
    <span class="token keyword">throws</span> InterruptedException<span class="token punctuation">,</span>ExecutionException<span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//提交tasks中所有任务，哪个任务县成功执行完毕，返回任务执行结果，其他任务取消</span>
<span class="token operator">&lt;</span>T<span class="token operator">></span> T <span class="token function">invokeAny</span><span class="token punctuation">(</span>Collection<span class="token operator">&lt;</span><span class="token operator">?</span> <span class="token keyword">extends</span> <span class="token class-name">Callable</span><span class="token operator">&lt;</span>T<span class="token operator">>></span> tasks<span class="token punctuation">)</span>
    <span class="token keyword">throws</span> InterruptedException<span class="token punctuation">,</span>ExecutionException<span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//提交tasks中所有任务，哪个任务先成功执行，返回此任务执行结果，其他任务取消，带超时时间</span>
<span class="token operator">&lt;</span>T<span class="token operator">></span> T <span class="token function">invokeAny</span><span class="token punctuation">(</span>Collection<span class="token operator">&lt;</span><span class="token operator">?</span> <span class="token keyword">extends</span> <span class="token class-name">Callable</span><span class="token operator">&lt;</span>T<span class="token operator">>></span> tasks<span class="token punctuation">,</span><span class="token keyword">long</span> timeout<span class="token punctuation">,</span>TimeUnit unit<span class="token punctuation">)</span>
    <span class="token keyword">throws</span> InterruptedException<span class="token punctuation">,</span>ExecutionException<span class="token punctuation">,</span>TimmeoutException<span class="token punctuation">;</span></code></pre>
<h4 id="关闭线程池"><a href="#关闭线程池" class="headerlink" title="关闭线程池"></a>关闭线程池</h4><h5 id="shutdown"><a href="#shutdown" class="headerlink" title="shutdown"></a>shutdown</h5><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/*
  线程池状态变为SHUTDOWN
  - 不会接收新任务
  - 但已提交的任务汇之星完
  - 此方法不会阻塞调用线程的执行
*/</span>
<span class="token keyword">void</span> <span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">shutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">final</span> ReentrantLock mainLock <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mainLock<span class="token punctuation">;</span>
        mainLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token function">checkShutdownAccess</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment" spellcheck="true">//修改线程池状态</span>
            <span class="token function">advanceRunState</span><span class="token punctuation">(</span>SHUTDOWN<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment" spellcheck="true">//仅打断空闲线程</span>
            <span class="token function">interruptIdleWorkers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token function">onShutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 扩展点 ScheduledThreadPoolExecutor</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">finally</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            mainLock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//尝试终结（没有运行的线程可以立刻终结，如果还有运行的线程也不会等）</span>
        <span class="token function">tryTerminate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h5 id="shutdonwnNow"><a href="#shutdonwnNow" class="headerlink" title="shutdonwnNow"></a>shutdonwnNow</h5><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/*
   线程池状态变为STOP
   - 不会接收新任务
   - 会将队列中的任务返回
   - 并用interrupt的方法中断正在执行的任务
*/</span></code></pre>
<pre class=" language-java"><code class="language-java">   <span class="token keyword">public</span> List<span class="token operator">&lt;</span>Runnable<span class="token operator">></span> <span class="token function">shutdownNow</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        List<span class="token operator">&lt;</span>Runnable<span class="token operator">></span> tasks<span class="token punctuation">;</span>
        <span class="token keyword">final</span> ReentrantLock mainLock <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mainLock<span class="token punctuation">;</span>
        mainLock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            <span class="token function">checkShutdownAccess</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment" spellcheck="true">//修改线程池状态</span>
            <span class="token function">advanceRunState</span><span class="token punctuation">(</span>STOP<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment" spellcheck="true">//打断所有线程</span>
            <span class="token function">interruptWorkers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment" spellcheck="true">//获取队列中剩余任务</span>
            tasks <span class="token operator">=</span> <span class="token function">drainQueue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">finally</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
            mainLock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
       <span class="token comment" spellcheck="true">//尝试终结</span>
        <span class="token function">tryTerminate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> tasks<span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h5 id="其他方法"><a href="#其他方法" class="headerlink" title="其他方法"></a>其他方法</h5><pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">//不在RUNNING状态的线程池，此方法就会返回true</span>
<span class="token keyword">boolean</span> <span class="token function">isShutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//线程池状态是否是TERMINATED</span>
<span class="token keyword">boolean</span> <span class="token function">isTerminated</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//调用shutdown后，由于调用线程并不会等待所有任务运行结束，因此如果他想在线程池RERMINATED后做些事情，可以利用此方法等待</span>
<span class="token keyword">boolean</span> <span class="token function">awaitTermination</span><span class="token punctuation">(</span><span class="token keyword">long</span> timeout<span class="token punctuation">,</span>TimeUnit unit<span class="token punctuation">)</span>
    <span class="token keyword">throws</span> InterruptedExceptionp<span class="token punctuation">;</span></code></pre>
<script>
        document.querySelectorAll('.github-emoji')
          .forEach(el => {
            if (!el.dataset.src) { return; }
            const img = document.createElement('img');
            img.style = 'display:none !important;';
            img.src = el.dataset.src;
            img.addEventListener('error', () => {
              img.remove();
              el.style.color = 'inherit';
              el.style.backgroundImage = 'none';
              el.style.background = 'none';
            });
            img.addEventListener('load', () => {
              img.remove();
            });
            document.body.appendChild(img);
          });
      </script>
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://gitee.com/yueyueniao-gif/yueyueniao-gif.git" rel="external nofollow noreferrer">Wang Yue Niao</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://gitee.com/yueyueniao-gif/yueyueniao-gif.git/yueyueniao-gif/2020/10/19/bing-fa-bian-cheng/">https://gitee.com/yueyueniao-gif/yueyueniao-gif.git/yueyueniao-gif/2020/10/19/bing-fa-bian-cheng/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="https://gitee.com/yueyueniao-gif/yueyueniao-gif.git" target="_blank">Wang Yue Niao</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            <span class="chip bg-color">无标签</span>
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/yueyueniao-gif/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/yueyueniao-gif/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        <img src="/yueyueniao-gif/medias/reward/alipay.jpg" class="reward-img" alt="支付宝打赏二维码">
                    </div>
                    <div id="wechat">
                        <img src="/yueyueniao-gif/medias/reward/wechat.png" class="reward-img" alt="微信打赏二维码">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/yueyueniao-gif/2020/11/02/java-ji-he/">
                    <div class="card-image">
                        
                        
                        <img src="/yueyueniao-gif/medias/featureimages/4.jpg" class="responsive-img" alt="java集合">
                        
                        <span class="card-title">java集合</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            java集合Collection
特点：代表任意类型的对象，无序、无下标、不能重复。
特点：
boolean add(Object obj)              //添加一个对象。
boolean addAll(Collect c) 
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2020-11-02
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/yueyueniao-gif/categories/java%E9%9B%86%E5%90%88/" class="post-category">
                                    java集合
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/yueyueniao-gif/tags/java%E9%9B%86%E5%90%88/">
                        <span class="chip bg-color">java集合</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/yueyueniao-gif/2020/10/11/java-duo-xian-cheng/">
                    <div class="card-image">
                        
                        
                        <img src="/yueyueniao-gif/medias/featureimages/4.jpg" class="responsive-img" alt="Java多线程">
                        
                        <span class="card-title">Java多线程</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            java线程理解
线程是调度CPU的最小单元，也叫轻量级进程（LWP）
两种线程模型
用户级线程（ULT）：用户程序实现，不依赖操作系统核心，引用提供创建、同步、调度和管理线程的函数来控制用户线程。不需要用户态/内核态切换，速度快。内核对U
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2020-10-11
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/yueyueniao-gif/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" class="post-category">
                                    多线程
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/yueyueniao-gif/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/">
                        <span class="chip bg-color">多线程</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>



<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/yueyueniao-gif/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/yueyueniao-gif/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/yueyueniao-gif/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/yueyueniao-gif/libs/codeBlock/codeShrink.js"></script>


<!-- 代码块折行 -->

<style type="text/css">
code[class*="language-"], pre[class*="language-"] { white-space: pre !important; }
</style>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/yueyueniao-gif/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h2, h3, h4'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h2, h3, h4').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>


<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script>

    <footer class="page-footer bg-color">
    
        <link rel="stylesheet" href="/yueyueniao-gif/libs/aplayer/APlayer.min.css">
<style>
    .aplayer .aplayer-lrc p {
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        font-size: 15px;
        color: #42b983;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    
</style>
<div class="">
    
    <div class="row">
        <meting-js class="col l8 offset-l2 m10 offset-m1 s12"
                   server="netease"
                   type="playlist"
                   id="2566555574"
                   fixed='true'
                   autoplay='false'
                   theme='#42b983'
                   loop='all'
                   order='random'
                   preload='auto'
                   volume='0.7'
                   list-folded='true'
        >
        </meting-js>
    </div>
</div>

<script src="/yueyueniao-gif/libs/aplayer/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>

    
    <div class="container row center-align" style="margin-bottom: 0px !important;">
       <h2>没有任何动物比蚂蚁更勤奋，然而它却最沉默寡言</h2><br><br>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script src="/yueyueniao-gif/js/search.js"></script>
<script type="text/javascript">
$(function () {
    searchFunc("/yueyueniao-gif/search.xml", 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/yueyueniao-gif/libs/materialize/materialize.min.js"></script>
    <script src="/yueyueniao-gif/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/yueyueniao-gif/libs/aos/aos.js"></script>
    <script src="/yueyueniao-gif/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/yueyueniao-gif/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/yueyueniao-gif/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/yueyueniao-gif/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/yueyueniao-gif/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

    

    

    

    
    <script src="/yueyueniao-gif/libs/instantpage/instantpage.js" type="module"></script>
    

</body>

</html>
